﻿//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: ObjectExpression.cs
//
//  Description: A storage independent expression tree.
// 
//--------------------------------------------------------------------------

using System;
using System.Reflection;
using System.Collections.Generic;
using Chili.Opf3.Storages;
using Chili.Opf3.Query.OPathParser;
using Chili.Opf3.Mapping;

namespace Chili.Opf3.Query
{
	/// <summary>
	/// Represents a parsed <see cref="Opf3.Query.ObjectQuery{T}">ObjectQuery</see>.
	/// </summary>
	/// <remarks>
	/// <para>Attention: This class could change in future versions.</para>
	/// <para>
	/// This class represents a parsed <see cref="Opf3.Query.ObjectQuery{T}">ObjectQuery</see>. 
	/// To create an ObjectExpression you have to use the <see cref="Opf3.Query.OPath.Parse">Parse</see>
	/// method of the <see cref="Opf3.Query.OPath">OPath</see> class. A parsed
	/// <see cref="Opf3.Query.ObjectQuery{T}">ObjectQuery</see> is still storage independent
	/// but is faster executed on the storage, since parsing of the content is no longer required.
	/// </para>
	/// </remarks>
	/// <example>
	/// The following example shows how to create a ObjectExpression by using the 
	/// <see cref="Opf3.Query.OPath">OPath</see> class. The ObjectExpression is then also compiled
	/// afterwards.
	/// <code lang="CS">
	/// // ... Other code
	/// 
	/// // Create an ObjectQuery for User persistent objects.
	/// // Add a condition to load only user with a name that contains "hri"
	/// ObjectQuery&lt;User&gt; objectQuery = 
	/// new ObjectQuery&lt;User&gt;("UserName like {0}", "%hri%");
	/// 
	/// // Create an ObjectExpression by parsing the ObjectQuery.
	/// ObjectExpression objectExpresion = OPath.Parse(objectQuery);
	/// 
	/// // Compile the ObjectExpression to get a CompildQuery.
	/// // You have to set the storage that is used to compile the query.
	/// CompiledQuery compiled = objectExpression.ToCompiledQuery(ObjectContext.Storage);
	/// 
	/// // ... Other code
	/// </code>
	/// </example>
	[Serializable]
	public sealed class ObjectExpression : Expression
	{
		private IList<OEItem> _items = new List<OEItem>();
		private IList<PersistentAttribute> _persistentAttributes;
		private Type _type;

		/// <summary>
		/// Creates a new instance of the <see cref="ObjectExpression">ObjectExpression
		/// Class</see>.
		/// </summary>
		/// <param name="queryType">
		/// Specifies the <see cref="Opf3.Query.QueryTypes">QueryType</see> of the
		/// <see cref="ObjectExpression">ObjectExpression</see>.
		/// </param>
		/// <param name="type">The primary type associated with the expression.</param>
		/// <param name="attribute">The primary persistent attribute of the type.</param>
		/// <exception cref="ArgumentException">Timeout is lower then zero.</exception>
		/// <exception cref="ArgumentNullException">PersistentAttribute is null.</exception>
		internal ObjectExpression(QueryTypes queryType, Type type, PersistentAttribute attribute) : base(queryType)
		{
			if (type == null)
				throw new ArgumentNullException("type");
			if (attribute == null)
				throw new ArgumentNullException("attribute");

			_type = type;
			
			_persistentAttributes = new List<PersistentAttribute>();
			_persistentAttributes.Add(attribute);
		}

		/// <summary>
		/// Returns the <see cref="Opf3.Query.OPathParser.OEItem">ObjectExpressionItems 
		/// (conditions, sort options, joins, brackets, comparer, concats, ...)</see> of the ObjectExpression.
		/// </summary>
		/// <value>
		/// A list of <see cref="Opf3.Query.OPathParser.OEItem">ObjectExpressionItems</see> 
		/// containing conditions, sort options, joins, brackets, comparer, concats, ... for the 
		/// <see cref="ObjectExpression">ObjectExpression</see>.
		/// </value>
		public IList<OEItem> Items
		{
			get { return _items; }
		}

		/// <summary>
		/// Returns the primary <see cref="TypeMapping">TypeMapping</see> associated with the
		/// <see cref="ObjectExpression">ObjectExpression</see>.
		/// </summary>
		public TypeMapping TypeMapping
		{
			get { return TypeMapping.GetTypeMapping(_type); }
		}

		/// <summary>
		/// Returns a list of <see cref="Opf3.PersistentAttribute">PersistentAttributes</see> of the 
		/// ObjectExpression. The attribute is the attribute from the entity that is requested from the storage 
		/// and it is used to compiled the ObjectExpression to a 
		/// <see cref="Opf3.Query.CompiledQuery">CompildQuery</see>.
		/// </summary>
		public IList<PersistentAttribute> PersistentAttributes
		{
			get { return _persistentAttributes; }
		}
	}
}
